﻿using System;

namespace cz.zcu.PreSti
{
    abstract public class BaseComponent
    {
        private int gettersCount;
        private Connection[] setters;

        public BaseComponent() : this(0, 0) { }

        public BaseComponent(int settersCount, int gettersCount)
        {
            this.gettersCount = gettersCount;
            setters = new Connection[settersCount];
        }

        public virtual object getValueFromGetter(int getterN) { return null; }

        public virtual void setValueToSetter(int setterN, object value) { }

        protected void retrieveValuesFromGetters()
        {
            for (int i = 0; i < setters.Length; i++)
            {
                if (setters[i].component != null)
                {
                    this.setValueToSetter(i, setters[i].component.getValueFromGetter(setters[i].getterN));
                }
            }
        }

        protected void convertValue(ref int destination, object source)
        {
            if (source is bool)
                destination = ((bool)source) == true ? 1 : 0;
            else if (source is int)
                destination = (int)source;
            else if (source is float)
                destination = (int)Math.Round((float)source);
            else if (source is double)
                destination = (int)Math.Round((double)source);
            else if (source is string)
                try
                {
                    destination = (int)Math.Round(double.Parse((string)source));
                }
                catch { }
        }

        protected void convertValue(ref float destination, object source)
        {
            if (source is bool)
                destination = ((bool)source) == true ? 1 : 0;
            else if (source is int)
                destination = (float)((int)source);
            else if (source is float)
                destination = (float)source;
            else if (source is double)
                destination = (float)((double)source);
            else if (source is string)
                try
                {
                    destination = float.Parse((string)source);
                }
                catch { }
        }

        protected void convertValue(ref double destination, object source)
        {
            if (source is bool)
                destination = ((bool)source) == true ? 1 : 0;
            else if (source is int)
                destination = (double)((int)source);
            else if (source is float)
                destination = (float)source;
            else if (source is double)
                destination = (double)source;
            else if (source is string)
                try
                {
                    destination = double.Parse((string)source);
                }
                catch { }
        }

        protected void convertValue(ref string destination, object source)
        {
            if (source is bool)
                destination = ((bool)source) == true ? "1" : "0";
            else if (source is int || source is float || source is double)
                destination = source.ToString();
            else if (source is string)
                destination = (string)source;
        }

        protected void convertValue(ref bool destination, object source)
        {
            if (source is bool)
                destination = (bool)source;
            else if (source is int)
                destination = ((int)source) == 0 ? false : true;
            else if (source is float)
                destination = ((float)source) == 0 ? false : true;
            else if (source is double)
                destination = ((double)source) == 0 ? false : true;
            else if (source is string)
                destination = ((string)source) == "0" || ((string)source) == "" ? false : true;
        }

        public void setupSetter(BaseComponent component)
        {
            setupSetter(0, component);
        }

        public void setupSetter(int setterN, BaseComponent component)
        {
            setupSetter(setterN, component, 0);
        }

        public void setupSetter(int setterN, BaseComponent component, int getterN)
        {
            setters[setterN].component = component;
            setters[setterN].getterN = getterN;
        }

        protected struct Connection
        {
            public BaseComponent component;
            public int getterN;
        }
    }
}